home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 1_0-2 / ASCII_CH / ASCII_CH.C
Text File  |  1986-08-14  |  17KB  |  402 lines

  1. /*************************************************************************/
  2. /*   Ascii Chart - a Desk Accessory for the Macintosh written by:        */
  3. /*   Wade S. Blomgren    (c) 1986             version 1.0                */
  4. /*   UC San Diego                                                        */
  5. /*                                                                       */
  6. /*   Both source and executable files may be freely distributed for      */
  7. /*   NON-COMMERCIAL USE ONLY provided this copyright notice is left      */
  8. /*   intact.                                                             */
  9. /*                                                                       */
  10. /*   This program is intended as an example for persons beginning to     */
  11. /*   learn about programming the Macintosh. It is NOT meant to be an     */
  12. /*   example of excellent programming or a particularly fabulous         */
  13. /*   idea for a program.  It IS supposed to be chock full of comments    */
  14. /*   and to have some examples of common uses for the toolbox.           */
  15. /*                                                                       */
  16. /*    This program was written using LightspeedC (c) from Think          */
  17. /*    Technologies, INC. and therefore includes material that is         */
  18. /*    copyright Think Technologies INC.                                  */
  19. /*                                                                       */
  20. /*    Some techniques were gleaned from a PD desk accessory called       */
  21. /*    ZoomIdle by Paul DuBois, University of Wisconsin                   */
  22. /*                                                                       */
  23. /*    Wade S. Blomgren  UCSD-ACS   mailcode B-028  La Jolla, CA 92093    */
  24. /*                                                                       */
  25. /*************************************************************************/
  26.  
  27. #include "devicemgr.h"
  28. #include "quickdraw.h"
  29. #include "windowmgr.h"
  30. #include "dialogmgr.h"
  31. #include "eventmgr.h"
  32. #include "controlmgr.h"
  33.  
  34. /* since this is a DA and not a standalone application we do not have to */
  35. /* initialize the various managers                                       */
  36.  
  37. /* Global Variables for the DA */
  38.  
  39. /* the chart data is stored in two dimensional arrays so we can use the */
  40. /* drawtext routine (faster than repeated calls to drawchar) (IM I-172) */
  41.  
  42.  char octdata[23][47] = {
  43.         "000 NUL  026 SYC  054 ,  102 B  130 X  156 n  ",
  44.         "001 SOH  027 ETB  055 -  103 C  131 Y  157 o  ",
  45.         "002 STX  030 CAN  056 .  104 D  132 Z  160 p  ",
  46.         "003 ETX  031 EM   057 /  105 E  133 [  161 q  ",
  47.         "004 EOT  032 SUB  060 0  106 F  134 \\  162 r  ",
  48.         "005 ENQ  033 ESC  061 1  107 G  135 ]  163 s  ",
  49.         "006 ACK  034 FS   062 2  110 H  136 ^  164 t  ",
  50.         "007 BEL  035 GS   063 3  111 I  137 _  165 u  ",
  51.         "010 BS   036 RS   064 4  112 J  140 `  166 v  ",
  52.         "011 HT   037 US   065 5  113 K  141 a  167 w  ",
  53.         "012 LF   040 SPA  066 6  114 L  142 b  170 x  ",
  54.         "013 VT   041 !    067 7  115 M  143 c  171 y  ",
  55.         "014 FF   042 ''   070 8  116 N  144 d  172 z  ",
  56.         "015 CR   043 #    071 9  117 O  145 e  173 {  ",
  57.         "016 SO   044 $    072 :  120 P  146 f  174 |  ",
  58.         "017 SI   045 %    073 ;  121 Q  147 g  175 }  ",
  59.         "020 DLE  046 &    074 <  122 R  150 h  176 ~  ",
  60.         "021 DC1  047 '    075 =  123 S  151 i  177 DEL",        
  61.         "022 DC2  050 (    076 >  124 T  152 j         ",
  62.         "023 DC3  051 )    077 ?  125 U  153 k         ",
  63.         "024 DC4  052 *    100 @  126 V  154 l         ",
  64.         "025 NAK  053 +    101 A  127 W  155 m         "};
  65.         
  66.  char decdata[23][47] = {
  67.        "000 NUL  022 SYC  044 ,  066 B  088 X  110 n  ",
  68.        "001 SOH  023 ETB  045 -  067 C  089 Y  111 o  ",
  69.        "002 STX  024 CAN  046 .  068 D  090 Z  112 p  ",
  70.        "003 ETX  025 EM   047 /  069 E  091 [  113 q  ",
  71.        "004 EOT  026 SUB  048 0  070 F  092 \\  114 r  ",
  72.        "005 ENQ  027 ESC  049 1  071 G  093 ]  115 s  ",
  73.        "006 ACK  028 FS   050 2  072 H  094 ^  116 t  ",
  74.        "007 BEL  029 GS   051 3  073 I  095 _  117 u  ",
  75.        "008 BS   030 RS   052 4  074 J  096 `  118 v  ",
  76.        "009 HT   031 US   053 5  075 K  097 a  119 w  ",
  77.        "010 LF   032 SPA  054 6  076 L  098 b  120 x  ",
  78.        "011 VT   033 !    055 7  077 M  099 c  121 y  ",
  79.        "012 FF   034 ''   056 8  078 N  100 d  122 z  ",
  80.        "013 CR   035 #    057 9  079 O  101 e  123 {  ",
  81.        "014 SO   036 $    058 :  080 P  102 f  124 |  ",
  82.        "015 SI   037 %    059 ;  081 Q  103 g  125 }  ",
  83.        "016 DLE  038 &    060 <  082 R  104 h  126 ~  ",
  84.        "017 DC1  039 '    061 =  083 S  105 i  127 DEL",        
  85.        "018 DC2  040 (    062 >  084 T  106 j         ",
  86.        "019 DC3  041 )    063 ?  085 U  107 k         ",
  87.        "020 DC4  042 *    064 @  086 V  108 l         ",
  88.        "021 NAK  043 +    065 A  087 W  109 m         " };
  89.        
  90.  char hexdata[23][47] = {
  91.  
  92.        "000 NUL  016 SYC  02C ,  042 B  058 X  06E n  ",
  93.        "001 SOH  017 ETB  02D -  043 C  059 Y  06F o  ",
  94.        "002 STX  018 CAN  02E .  044 D  05A Z  070 p  ",
  95.        "003 ETX  019 EM   02F /  045 E  05B [  071 q  ",
  96.        "004 EOT  01A SUB  030 0  046 F  05C \\  072 r  ",  /* escape the \ character */
  97.        "005 ENQ  01B ESC  031 1  047 G  05D ]  073 s  ",
  98.        "006 ACK  01C FS   032 2  048 H  05E ^  074 t  ",
  99.        "007 BEL  01D GS   033 3  049 I  05F _  075 u  ",
  100.        "008 BS   01E RS   034 4  04A J  060 `  076 v  ",
  101.        "009 HT   01F US   035 5  04B K  061 a  077 w  ",
  102.        "00A LF   020 SPA  036 6  04C L  062 b  078 x  ",
  103.        "00B VT   021 !    037 7  04D M  063 c  079 y  ",
  104.        "00C FF   022 ''   038 8  04E N  064 d  07A z  ",
  105.        "00D CR   023 #    039 9  05F O  065 e  07B {  ",
  106.        "00E SO   024 $    03A :  050 P  066 f  07C |  ",
  107.        "00F SI   025 %    03B ;  051 Q  067 g  07D }  ",
  108.        "010 DLE  026 &    03C <  052 R  068 h  07E ~  ",
  109.        "011 DC1  027 '    03D =  053 S  069 i  07F DEL",        
  110.        "012 DC2  028 (    03E >  054 T  06A j         ",
  111.        "013 DC3  029 )    03F ?  055 U  06B k         ",
  112.        "014 DC4  02A *    040 @  056 V  06C l         ",
  113.        "015 NAK  02B +    041 A  057 W  06D m         " };
  114.    
  115.     DCtlPtr dce;         /* pointer to the device control entry struct */
  116.     int DAisOpen = 0;    /* flag so we know if the DA is already open  */
  117.     
  118. #define rALRT 0          /* the About box's resource ID # */   
  119.  
  120. /* allocate control handles to the various control buttons */
  121.        
  122.     ControlHandle OctPtr,HexPtr,DecPtr,curControl,whichControl,AbPtr;
  123.     
  124.  
  125.     int line;     /* counter for the text drawing loop */
  126.     int y;        /* coordinate variable for positioning the text */
  127.     
  128. /* define rectangles for the DA's window and the control buttons  */
  129. /* BlankRect is the entire data area & is used to erase the data  */
  130.     static Rect bounds = { 60,60, 335, 350 };
  131.     static Rect OctRect = { 225,12,242,80 };
  132.     static Rect HexRect = { 225,115, 242, 185 };
  133.     static Rect DecRect = { 225,200, 242, 268 };
  134.     static Rect AbRect  = { 250,85, 270, 205 };
  135.     static Rect BlankRect = { 3,12,220,280 };
  136.     
  137. /* various functions begin here - see 'main' for calling sequence  */
  138.     
  139.     
  140. aboutDA()                    /* creates an alert dialog message about  */
  141.                              /* the DA and gives an OK button to exit  */
  142. {
  143.   /* the alert resource and accompanying item list are stored in a   */
  144.   /* file called "ascii_chart.rsrc" which was created with ResEdit   */
  145.   /* ..since the OK button is the default (highlighted) choice, we   */
  146.   /* do not have to have a filterProc   (IM I-419)                   */
  147.   /* If you examine the DA file with ResEdit, you will see that the  */
  148.   /* resource ID for the ALRT is -16000, which translates into an    */
  149.   /* 'owned' resource ID of '0' (zero) for a DRVR (our program)      */
  150.   /* with an ID of '12'. This is the ID number that LightspeedC      */
  151.   /* assigns to a Desk Accesory that it creates.  When you install   */
  152.   /* a DA with the Font/DA mover, it checks to see that the ID# does */
  153.   /* not conflict with that of an existing DA. If it does, the F/DA  */
  154.   /* will change our DA's ID to an unused #, and all of the 'owned'  */
  155.   /* resource ID's will be shifted accordingly. Read IM I-108,109.   */
  156.      
  157.   Alert(rsrcID(rALRT),0L);   /* invoke the alert   (IM I-418) */
  158.   
  159.  
  160. /* this routine from the LightspeedC demo DA by Michael Kahl...     */
  161. /* returns the correct resource ID number "no matter what driver #  */
  162. /* the Font/DA Mover has assigned us... "  (IM I-109)               */
  163.  
  164. rsrcID(id)
  165. {
  166.      return(0xc000 + (~dce->dCtlRefNum << 5 ) + id);
  167. }
  168.  
  169.   
  170. /* window update routine -  if it's a result of a radix change, scope */
  171. /* is 0 (update everything) - if it is a system update event, update  */
  172. /* only the area that needs it, by using BeginUpdate & EndUpdate      */
  173. /* (see calls to 'updateDisplay()' in 'main' and 'DAEvent'            */
  174.  
  175. updateDisplay(scope)   
  176. int scope;
  177. {
  178.  
  179. GrafPtr currentPort;
  180. Ptr dataAddr;                /* a generic 'pointer' data type */
  181.  
  182. GetPort(¤tPort);       /* save the current grafport  (IM I-447)  */
  183. SetPort(dce->dCtlWindow);    /* set the grafport to our window         */
  184.  
  185.   if (scope)
  186.     BeginUpdate(dce->dCtlWindow);   /* set the visRgn to only the part */
  187.                                     /* that needs updating (IM I-292)  */
  188.                                     /* otherwise, redraw the whole window */
  189.                    
  190.     DrawControls(dce->dCtlWindow);  /* draw the controls in our window   */
  191.     EraseRect(&BlankRect);          /* blank out the old data (IM I-177) */
  192.     y = 10;
  193.     
  194.     if (curControl == OctPtr)     /* determine which control was pressed */
  195.        dataAddr = (Ptr) octdata;   /* & cast the address of the 2D array */
  196.     else if (curControl == DecPtr) /* into our generic data pointer      */
  197.        dataAddr = (Ptr) decdata;
  198.     else if (curControl == HexPtr)
  199.        dataAddr = (Ptr) hexdata;
  200.        
  201.     TextFont(4);   /* Monaco font for evenly spaced columns (IM I-219)  */
  202.     TextSize(9);   /* these are quickdraw functions                     */
  203.    
  204.     for (line  = 0; line  < 22; line++) { 
  205.     
  206.     /* we have 23 lines per 'page' - use quickdraw to output the data   */
  207.     /* the starting address for DrawText is (line# * 47) to get to the  */
  208.     /* proper position in the 2D array                                  */
  209.      
  210.          MoveTo(12,y);           
  211.          DrawText(dataAddr + (line * 47),0,46);    /* (IM I-172)        */
  212.           y = y +10;
  213.           }  
  214.  
  215.     if (scope) EndUpdate(dce->dCtlWindow);          
  216.                                 
  217. SetPort(currentPort);         /* restore the current grafport (IM I-447) */
  218.  
  219. }    /* end of updateDisplay */ 
  220.  
  221.    
  222.  
  223. openDA()              /* open the desk accessory */
  224. {
  225.     
  226.     GrafPtr currentPort;
  227.     
  228.     if (DAisOpen) return;     /* if it is already open, just ignore */
  229.     GetPort(¤tPort);    /* save the current grafport */
  230.  
  231. /* create our window, set the device control entry (dce) window field  */
  232. /* to our window, set the window's windowKind field to the reference # */
  233. /* for the driver  (IM I-445)                                          */
  234.     
  235.     dce->dCtlWindow = NewWindow(0,&bounds,"\pAscii Chart",0,16,-1,1,0);
  236.     ((WindowPeek) (dce->dCtlWindow))->windowKind = dce->dCtlRefNum;
  237.     
  238.      SetPort(dce->dCtlWindow);    /* set the grafport to our window */
  239.      ShowWindow(dce->dCtlWindow); /* display the window             */
  240.      
  241.      
  242.     /* create new controls for the various radixes and the about box */
  243.     /* set the octal radix control to be 'on'... (IM I-319)          */ 
  244.     OctPtr = NewControl(dce->dCtlWindow,&OctRect,"\poctal",1,1,0,1,2,0);
  245.      HexPtr = NewControl(dce->dCtlWindow,&HexRect,"\phex",1,0,0,1,2,0);
  246.      DecPtr = NewControl(dce->dCtlWindow,&DecRect,"\pdecimal",1,0,0,1,2,0);
  247.      AbPtr  = NewControl(dce->dCtlWindow,&AbRect,"\pabout ascii chart",1,1,0,0,0,0);
  248.   
  249.      curControl = OctPtr;     /* set default for current control button */
  250.      
  251. /* we do not need to explicitly call "updateDisplay" because the open  */
  252. /* routine will cause an update event to be sent to the Desk Manager   */
  253.      
  254.      DAisOpen = 1;                 /* set the DA 'on' (our own flag)   */
  255.      SetPort(currentPort);         /* restore original grafport        */
  256.      
  257. return(0);
  258.    
  259. }        /* end of the openDA routine */
  260.  
  261.  
  262. DAevent(theEvent)
  263. EventRecord *theEvent;      /* argument is a pointer to an event record */
  264. {
  265.  
  266. GrafPtr currentPort;
  267.  
  268. GetPort(¤tPort);     /* save the system's current grafport   */
  269.  
  270. /* at this point we know there has been an event in the DA window  */
  271. /* content region, so we must process the event */
  272.  
  273. SetPort(dce->dCtlWindow);     /* set the port to our window        */
  274.    
  275. switch (theEvent->what) {     /* examine the 'what' field of event */
  276.                               /* (IM I-263,264)                    */
  277.      case activateEvt:          /* the DA window has become active   */     
  278.             updateDisplay(1);
  279.             return(0); 
  280.             
  281.      case updateEvt:          /* we need to update (result of drag, etc) */     
  282.             updateDisplay(1);
  283.             return(0); 
  284.             
  285.      case mouseDown:
  286.           /* convert the location to local coordinates  (IM I-193,323)   */
  287.          GlobalToLocal(&(theEvent->where));
  288.    
  289.          /* find where mouse was pressed - (the part code) (IM I-334)    */
  290.        
  291.          switch (FindControl(theEvent->where,dce->dCtlWindow,&whichControl)) {
  292.              
  293.            case (11):         /* a RADIO button has been hit - track it  */
  294.            
  295.                /* track control routine makes sure mouse is released in button */
  296.                if (TrackControl(whichControl,theEvent->where,0)) {
  297.                
  298.                    if (whichControl != curControl) {      /* a new radix */
  299.                      SetCtlValue(curControl,0);
  300.                      curControl = whichControl; /* set new 'current' ctl */
  301.                      SetCtlValue(curControl,1);
  302.                      updateDisplay(0);            /* update whole window */
  303.                      }                 /* end new radix */
  304.                }                /* end if track control */
  305.                break;
  306.            case (10):      /* SIMPLE button (must be the about box) */
  307.            
  308.               /* create an alert dialog with an OK button to terminate */
  309.            
  310.               aboutDA();
  311.               break;
  312.                   
  313.            } /* end possible control mousedown */
  314.            
  315.          LocalToGlobal(&theEvent->where); /* put the coordinates back to global */
  316.  
  317.      } /* end of the event switch */
  318.                
  319.  SetPort(currentPort);   /* restore the grafport */
  320.          
  321. }   /* end of DAevent */
  322.  
  323.  
  324.  
  325. /* close DA function */
  326.  
  327. closeDA()
  328. {
  329.    GrafPtr currentPort;
  330.    
  331.    GetPort(¤tPort);         /* save the system's grafport */
  332.    DisposeWindow(dce->dCtlWindow);/* dispose our window */
  333.    dce->dCtlWindow = 0L;          /* set the driver's window ptr to null */
  334.                                   /* (IM I-446) */
  335.    SetPort(currentPort);          /* restore the system's grafport */
  336.    return(0);
  337.  
  338. }
  339. /* main driver routine - three parameters are passed to us through the */
  340. /* device manager.   1. the control parameter pointer                  */
  341. /*                   2. the pointer to the dce record                  */
  342. /*                   3. the  driver routine (open, control, or close)  */
  343. /*                   (IM II-201, I-445 )                               */
  344.  
  345.      
  346. main (p,d,n)
  347. cntrlParam *p;
  348. DCtlPtr d;
  349. int n;
  350.  
  351.  
  352. {
  353.  
  354. if (d->dCtlStorage == 0 ) {
  355.      if (n == 0) {            /* open but no data */
  356.           SysBeep(3);
  357.           CloseDriver(d->dCtlRefNum);
  358.           }
  359.           return(0);
  360.     }
  361.     
  362.     dce = d;
  363.  
  364. /* find the appropriate driver routine */
  365.     
  366.     switch(n) {        /* 0 = open, 2 = control event, 4 = close */
  367.     
  368.        case 0:         /* open the DA */
  369.           openDA();
  370.           break;
  371.           
  372.        case 2:         /* action in the DA */
  373.           switch(p->csCode) {
  374.           
  375.                case accEvent:
  376.                   DAevent(((EventRecord *) * (long *) &p->csParam)); 
  377.                   
  378.  /* casting the *address of* p->csParam as an pointer to a long, and the */
  379.  /* long is cast as a pointer to a pointer to an Event Record (I think?) */
  380.  /* (from ZoomIdle 1.1 by Paul DuBois)                                   */
  381.  /* the pointer is passed as the parameter to DAevent                    */
  382.                   
  383.                   
  384.                  }  /* end of case 2 switch */
  385.                  break;
  386.              
  387.        case 4:       /* close box has been clicked */
  388.           closeDA();
  389.           break;
  390.           
  391.      }   /* end of the main switch */
  392.      
  393.    return(0);
  394.    
  395.  
  396. }       /* end of main */
  397.  
  398.  
  399.     
  400.  
  401.